package com.angel.config;



import com.angel.shiro.*;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.*;


/**
 * shiro配置
 * @author Rabit
 */

@Configuration
public class ShiroConfig {
   private Logger logger = LoggerFactory.getLogger(this.getClass());
   @Autowired
    MyConfig myConfig;
    /**
     * ShiroFilterFactoryBean 处理拦截资源文件问题。
     * 注意：单独一个ShiroFilterFactoryBean配置是或报错的，以为在
     * 初始化ShiroFilterFactoryBean的时候需要注入：SecurityManager
     * Filter Chain定义说明 1、一个URL可以配置多个Filter，使用逗号分隔 2、当设置多个过滤器时，全部验证通过，才视为通过
     * 3、部分过滤器可指定参数，如perms，roles
     */
    @Bean
    public ShiroFilterFactoryBean shirFilter(@Qualifier("securityManager") SecurityManager securityManager) {
       ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
       //获取filters
        Map<String, Filter> filters=shiroFilterFactoryBean.getFilters();
        //将自定义 的FormAuthenticationFilter注入shiroFilter中
        filters.put("authc", new SelFormAuthenticationFilter());
        filters.put("perms",new URLPermissionsFilter());
        // 必须设置 SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 如果不设置默认会自动寻找Web工程根目录下的"/login.html"页面
        shiroFilterFactoryBean.setLoginUrl("/login");

        // 登录成功后要跳转的链接
        shiroFilterFactoryBean.setSuccessUrl("/index");


        // 拦截器.
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // 配置不会被拦截的链接 顺序判断
        filterChainDefinitionMap.put("/"+myConfig.getVitrPath()+"/**", "anon");
        filterChainDefinitionMap.put("/userlogin", "anon");
        filterChainDefinitionMap.put("/user/**", "anon");
        filterChainDefinitionMap.put("/druid/**","anon");
        filterChainDefinitionMap.put("/resources/**", "anon");
        filterChainDefinitionMap.put("/r/**", "anon");
        filterChainDefinitionMap.put("/l/**", "anon");//用户登陆后首页
        filterChainDefinitionMap.put("/file/**", "anon");
        filterChainDefinitionMap.put("/f/**", "anon");
        /**
         * 配置shiro拦截器链
         *
         * anon  不需要认证
         * authc 需要认证
         * user  验证通过或RememberMe登录的都可以
         *
         */
        //配置记住我或认证通过可以访问的地址
   //     filterChainDefinitionMap.put("/", "user");
        filterChainDefinitionMap.put("/login", "authc");
      //  filterChainDefinitionMap.put("/u/**","authc,perms");
        // 配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了
        filterChainDefinitionMap.put("/logout", "logout");

        //所有url都必须有user权限才可以访问 一般讲/**放在最后面
        filterChainDefinitionMap.put("/**", "user");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        logger.info("================Shiro拦截器工厂类注入成功================");
        return shiroFilterFactoryBean;

    }


    /**
     * 配置核心安全事物管理器
     *
     * @param systemAdminAuthorizingRealm
     * @return
     */
    @Bean(name = {"securityManager"})
    public SecurityManager securityManager(@Qualifier("selfRealmAuthenticator")SelfRealmAuthenticator selfRealmAuthenticator,@Qualifier("systemAdminAuthorizingRealm") SystemAdminAuthorizingRealm systemAdminAuthorizingRealm,@Qualifier("usernAuthorizingRealm")UserAuthorizingRealm userAuthorizingRealm) {
        logger.info("===========shrio已加载===================");
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //设置realms
        List<Realm> authorizingRealmList = Collections.synchronizedList(new ArrayList<org.apache.shiro.realm.Realm>());
        systemAdminAuthorizingRealm.setPermissionResolver(new CustomerPermissionResolver());
        authorizingRealmList.add(systemAdminAuthorizingRealm);
        authorizingRealmList.add(userAuthorizingRealm);
        securityManager.setRealms(authorizingRealmList);
        securityManager.setRememberMeManager(rememberMeManager());
        //配置session管理器实现单用户登录
        securityManager.setSessionManager(new DefaultWebSessionManager());
        return securityManager;
    }

    @Bean(name = {"selfRealmAuthenticator"})
    public SelfRealmAuthenticator selfRealmAuthenticator() {
        return new SelfRealmAuthenticator();
    }

    /**
     * admin身份认证realm (这个需要自己写，账号密码校验；权限等)
     *
     * @return
     */
    @Bean(name = {"systemAdminAuthorizingRealm"})
    public SystemAdminAuthorizingRealm systemAuthorizingRealm() {
        return new SystemAdminAuthorizingRealm();
    }

    /**
     * admin身份认证realm (这个需要自己写，账号密码校验；权限等)
     *
     * @return
     */
    @Bean(name = {"usernAuthorizingRealm"})
    public UserAuthorizingRealm usernAuthorizingRealm() {
        return new UserAuthorizingRealm();
    }


    /**
     * 记住我cookie
     *
     * @return
     */
    public SimpleCookie rememBerMeCookie() {
        logger.info("======记住我cookie---ShiroConfiguration.rememberMeCookie()========================");
        //这个参数是cookie的名称，对应前端的checkbox的name = rememberMe
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        //<!-- 记住我cookie生效时间30天 ,单位秒;-->
        int maxAge = 259200;
        simpleCookie.setMaxAge(maxAge);
        return simpleCookie;
    }

    /**
     * cookie管理对象
     *
     * @return
     */
    @Bean
    public CookieRememberMeManager rememberMeManager() {
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememBerMeCookie());
        return cookieRememberMeManager;
    }
}
